package com.googlecode.project4uz.encoder;

import org.openrdf.model.impl.LiteralImpl;
import org.openrdf.model.impl.StatementImpl;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFWriter;

import com.googlecode.project4uz.interfaces.Loggable;

/**
 * Bezposrednio dziala na bibliotece Rio dla zapisu danych do strumienia w formacie RDF.
 * @author Daniel Kur
 */
class RioWriterHelper implements Loggable {
	/**
	 * Prefix uzywany w zapisie do formatu RDF w calym strumieniu.
	 */
	private static final String GLOBAL = "rdf";
	
	/**
	 * Writer piszacy do formatu RDF w strumieniu.
	 */
	protected final transient RDFWriter rdf;
	
	/**
	 * Tworzy obiekt writera obiektow do formatu RDF.
	 * @param writer - typ writera z jakiego ma korzystac przy zapisie do strumienia.
	 */
	protected RioWriterHelper(final RDFWriter writer) {
		this.rdf = writer;
		this.initializeNamespaces();
	}

	/**
	 * Inicjalizuje standardowa przestrzen nazw.
	 */
	private final void initializeNamespaces() {
		try {
			rdf.handleNamespace("owner", "owner:/");
			rdf.handleNamespace("object", "object:/");
			rdf.handleNamespace("float", "float:/");
			rdf.handleNamespace("byte", "byte:/");
			rdf.handleNamespace("short", "short:/");
			rdf.handleNamespace("long", "long:/");
			rdf.handleNamespace("char", "char:/");
			rdf.handleNamespace("int", "int:/");
			rdf.handleNamespace("double", "double:/");
			rdf.handleNamespace("boolean", "boolean:/");
			rdf.handleNamespace("String", "String:/");
			rdf.handleNamespace("serial", "serial:/");
			rdf.handleNamespace("reference", "reference:/");
			rdf.handleNamespace("array", "array:/");
			rdf.handleNamespace("collection", "collection:/");
			rdf.handleNamespace("map", "map:/");
			rdf.handleNamespace("key", "key:/");
			rdf.handleNamespace("value", "value:/");
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge zainicjalizowac standardowych przestrzeni nazw.");
		}
	}
	
	/**
	 * Dodaje do strumienia zapis komentarza w formacie RDF.
	 * @param comment - tresc dodawanego komentarza
	 */
	protected final void addComment(final String comment) {
		try {
			this.rdf.handleComment(comment);
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac komentarza: " + comment);
		}
	}
	
	/**
	 * Dodaje do strumienia zapis wyrazenia w formacie RDF.
	 * @param id - unikalny identyfikator obiektu nadrzednego.
	 * @param name - nazwa zmiennej.
	 * @param type - typ zmiennej.
	 * @param value - wartosc zmiennej.
	 */
	protected final void addExpression(final String id, final String type, final String name, final String value) {
		try {
			rdf.handleStatement(new StatementImpl(new URIImpl(GLOBAL + ":/" + id),
													new URIImpl(type + ":/" + name),
													new LiteralImpl(value)));
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac wyrazenia: " + name);
		}
	}
	
	/**
	 * Dodaje do strumienia zapis wlasciciela w formacie RDF.
	 * @param id - unikalny identyfikator obiektu nadrzednego.
	 * @param type - typ zmiennej.
	 * @param refID - zapis typu zmiennej w formacie RDF.
	 */
	protected final void addOwner(final String id, final String type, final String refId) {
		try {
			rdf.handleStatement(new StatementImpl(new URIImpl(GLOBAL + ":/" + id),
													new URIImpl("owner:/" + type),
													new URIImpl(GLOBAL + ":/" + refId)));
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac wlasciciela: " + type);
		}
	}
	
	/**
	 * Dodaje do strumienia zapis primitywu w formacie RDF.
	 * @param id - unikalny identyfikator obiektu nadrzednego.
	 * @param type - typ zmiennej primitywnej.
	 * @param name - nazwa zmiennej typu primitywnego.
	 * @param value - wartosc zmiennej primitywnej.
	 */
	protected final void addPrimitive(final String id, final String type, final String name, final String value) {
		try {
			rdf.handleStatement(new StatementImpl(new URIImpl(GLOBAL + ":/" + id),
													new URIImpl(type + ":/" + name),
													new LiteralImpl(value)));
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac typu prymitywnego: " + name);
		}
	}

	/**
	 * Dodaje do strumienia zapis referencji w formacie RDF.
	 * @param id - unikalny identyfikator obiektu nadrzednego.
	 * @param name - nazwa zmiennej typu referencyjnego.
	 * @param type - typ zmiennej referencyjnej.
	 * @param refId - unikalny identyfikator obiektu podrzednego.
	 */
	protected final void addReference(final String id, final String name, final String type, final String refId) {
		try {
			rdf.handleStatement(new StatementImpl(new URIImpl(GLOBAL + ":/" + id),
													new URIImpl(type + ":/" + name),
													new URIImpl(GLOBAL + ":/" + refId)));
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac typu referencyjnego: " + name);
		}
	}

	/**
	 * Dodaje do strumienia zapis tablicy w formacie RDF.
	 * @param id - unikalny identyfikator obiektu nadrzednego.
	 * @param name - nazwa zmiennej typu tablicowego.
	 * @param arrayId - unikalny identyfikator obiektu podrzednego.
	 */
	protected final void addArray(final String id, final String name, final String arrayId) {
		try {
			rdf.handleStatement(new StatementImpl(new URIImpl(GLOBAL + ":/" + id),
													new URIImpl("array:/" + name),
													new URIImpl(GLOBAL + ":/" + arrayId)));
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac typu tablicowego: " + name);
		}
	}

	/**
	 * Dodaje do strumienia zapis kolekcji w formacie RDF.
	 * @param id - unikalny identyfikator obiektu nadrzednego.
	 * @param name - nazwa zmiennej instancji kolekcji.
	 * @param colId - unikalny identyfikator obiektu podrzednego.
	 */
	protected final void addCollection(final String id, final String name, final String colId) {
		try {
			rdf.handleStatement(new StatementImpl(new URIImpl(GLOBAL + ":/" + id),
													new URIImpl("collection:/" + name),
													new URIImpl(GLOBAL + ":/" + colId)));
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac kolekcji: " + name);
		}
	}

	/**
	 * Dodaje do strumienia zapis mapy w formacie RDF.
	 * @param id - unikalny identyfikator obiektu nadrzednego.
	 * @param name - nazwa zmiennej instancji mapy.
	 * @param mapId - unikalny identyfikator obiektu podrzednego.
	 */
	protected final void addMap( final String id, final String name, final String mapId ) {
		try {
			rdf.handleStatement(new StatementImpl(new URIImpl(GLOBAL + ":/" + id),
													new URIImpl("map:/" + name),
													new URIImpl(GLOBAL + ":/" + mapId)));
		} catch(RDFHandlerException e) {
			LOG.warning("Nie moge dodac mapy: " + name);
		}
	}
}
